package cluster

import (
	"fmt"
	"time"

	"github.com/AsynkronIT/protoactor-go/actor"

	nactor "nggs/actor"
	nexport "nggs/export"
	nservice "nggs/service"
)

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 请求全局配置
type requestGlobalConfig struct {
}

// 请求全局配置回复
type responseGlobalConfig struct {
	globalConfig nexport.IClusterGlobalConfig
}

func requestResponseGlobalConfig(pid *actor.PID, send *requestGlobalConfig) (*responseGlobalConfig, error) {
	return requestResponseGlobalConfigT(pid, send, 10000*time.Millisecond)
}

func requestResponseGlobalConfigT(pid *actor.PID, send *requestGlobalConfig, timeout time.Duration) (*responseGlobalConfig, error) {
	if nactor.IsPIDPtrEmpty(pid) {
		return nil, fmt.Errorf("pid is nil")
	}
	f := nactor.RootContext.RequestFuture(pid, send, timeout)
	iRecv, err := f.Result()
	if err != nil {
		return nil, err
	}
	recv, ok := iRecv.(*responseGlobalConfig)
	if !ok {
		return nil, fmt.Errorf("recv %#v is not responseGlobalConfig", recv)
	}
	return recv, nil
}

// 请求服务全局配置
type requestServiceGlobalConfig struct {
	name string
}

// 请求服务全局配置回复
type responseServiceGlobalConfig struct {
	err                 error
	serviceGlobalConfig nexport.IServiceGlobalConfig
}

func requestResponseServiceGlobalConfig(pid *actor.PID, send *requestServiceGlobalConfig) (*responseServiceGlobalConfig, error) {
	return requestResponseServiceGlobalConfigT(pid, send, 10000*time.Millisecond)
}

func requestResponseServiceGlobalConfigT(pid *actor.PID, send *requestServiceGlobalConfig, timeout time.Duration) (*responseServiceGlobalConfig, error) {
	if nactor.IsPIDPtrEmpty(pid) {
		return nil, fmt.Errorf("pid is nil")
	}
	f := nactor.RootContext.RequestFuture(pid, send, timeout)
	iRecv, err := f.Result()
	if err != nil {
		return nil, err
	}
	recv, ok := iRecv.(*responseServiceGlobalConfig)
	if !ok {
		return nil, fmt.Errorf("recv %#v is not responseServiceGlobalConfig", recv)
	}
	return recv, nil
}

// 请求服务配置
type requestServiceConfig struct {
	name string
	id   int
}

// 请求服务配置回复
type responseServiceConfig struct {
	err           error
	serviceConfig nexport.IServiceConfig
}

func requestResponseServiceConfig(pid *actor.PID, send *requestServiceConfig) (*responseServiceConfig, error) {
	return requestResponseServiceConfigT(pid, send, 10000*time.Millisecond)
}

func requestResponseServiceConfigT(pid *actor.PID, send *requestServiceConfig, timeout time.Duration) (*responseServiceConfig, error) {
	if nactor.IsPIDPtrEmpty(pid) {
		return nil, fmt.Errorf("pid is nil")
	}
	f := nactor.RootContext.RequestFuture(pid, send, timeout)
	iRecv, err := f.Result()
	if err != nil {
		return nil, err
	}
	recv, ok := iRecv.(*responseServiceConfig)
	if !ok {
		return nil, fmt.Errorf("recv %#v is not responseServiceConfig", recv)
	}
	return recv, nil
}

// 请求服务信息
type requestServiceInfo struct {
	name string
	id   nexport.ServiceID
}

// 请求服务信息回复
type responseServiceInfo struct {
	err  error
	info *nservice.Info
}

func requestResponseServiceInfo(pid *actor.PID, send *requestServiceInfo) (*responseServiceInfo, error) {
	return requestResponseServiceInfoT(pid, send, 10000*time.Millisecond)
}

func requestResponseServiceInfoT(pid *actor.PID, send *requestServiceInfo, timeout time.Duration) (*responseServiceInfo, error) {
	if nactor.IsPIDPtrEmpty(pid) {
		return nil, fmt.Errorf("pid is nil")
	}
	f := nactor.RootContext.RequestFuture(pid, send, timeout)
	iRecv, err := f.Result()
	if err != nil {
		return nil, err
	}
	recv, ok := iRecv.(*responseServiceInfo)
	if !ok {
		return nil, fmt.Errorf("recv %#v is not responseServiceInfo", recv)
	}
	return recv, nil
}

// 请求服务实例
type requestServiceInstance struct {
	name string
	id   nexport.ServiceID
}

// 请求服务实例回复
type responseServiceInstance struct {
	err      error
	instance *nservice.Instance
}

func requestResponseServiceInstance(pid *actor.PID, send *requestServiceInstance) (*responseServiceInstance, error) {
	return requestResponseServiceInstanceT(pid, send, 10000*time.Millisecond)
}

func requestResponseServiceInstanceT(pid *actor.PID, send *requestServiceInstance, timeout time.Duration) (*responseServiceInstance, error) {
	if nactor.IsPIDPtrEmpty(pid) {
		return nil, fmt.Errorf("pid is nil")
	}
	f := nactor.RootContext.RequestFuture(pid, send, timeout)
	iRecv, err := f.Result()
	if err != nil {
		return nil, err
	}
	recv, ok := iRecv.(*responseServiceInstance)
	if !ok {
		return nil, fmt.Errorf("recv %#v is not responseServiceInstance", recv)
	}
	return recv, nil
}

// 请求上传服务实例
type requestPutServiceInstance struct {
	name     string
	id       nexport.ServiceID
	instance *nservice.Instance
}

// 请求上传服务实例回复
type responsePutServiceInstance struct {
	err error
}

func requestResponsePutServiceInstance(pid *actor.PID, send *requestPutServiceInstance) (*responsePutServiceInstance, error) {
	return requestResponsePutServiceInstanceT(pid, send, 10000*time.Millisecond)
}

func requestResponsePutServiceInstanceT(pid *actor.PID, send *requestPutServiceInstance, timeout time.Duration) (*responsePutServiceInstance, error) {
	if nactor.IsPIDPtrEmpty(pid) {
		return nil, fmt.Errorf("pid is nil")
	}
	f := nactor.RootContext.RequestFuture(pid, send, timeout)
	iRecv, err := f.Result()
	if err != nil {
		return nil, err
	}
	recv, ok := iRecv.(*responsePutServiceInstance)
	if !ok {
		return nil, fmt.Errorf("recv %#v is not responsePutServiceInstance", recv)
	}
	return recv, nil
}

// 请求锁定服务坑位
type requestTryLockServicePosition struct {
	name     string
	id       nexport.ServiceID
	instance *nservice.Instance
}

// 请求锁定服务坑位回复
type responseTryLockServicePosition struct {
	err error
}

func requestResponseTryLockServicePosition(pid *actor.PID, send *requestTryLockServicePosition) (*responseTryLockServicePosition, error) {
	return requestResponseTryLockServicePositionT(pid, send, 10000*time.Millisecond)
}

func requestResponseTryLockServicePositionT(pid *actor.PID, send *requestTryLockServicePosition, timeout time.Duration) (*responseTryLockServicePosition, error) {
	if nactor.IsPIDPtrEmpty(pid) {
		return nil, fmt.Errorf("pid is nil")
	}
	f := nactor.RootContext.RequestFuture(pid, send, timeout)
	iRecv, err := f.Result()
	if err != nil {
		return nil, err
	}
	recv, ok := iRecv.(*responseTryLockServicePosition)
	if !ok {
		return nil, fmt.Errorf("recv %#v is not responseTryLockServicePosition", recv)
	}
	return recv, nil
}

// 请求服务负载
type requestServicePayload struct {
	name string
	id   nexport.ServiceID
}

// 请求服务负载回复
type responseServicePayload struct {
	err     error
	payload nexport.Payload
}

func requestResponseServicePayload(pid *actor.PID, send *requestServicePayload) (*responseServicePayload, error) {
	return requestResponseServicePayloadT(pid, send, 10000*time.Millisecond)
}

func requestResponseServicePayloadT(pid *actor.PID, send *requestServicePayload, timeout time.Duration) (*responseServicePayload, error) {
	if nactor.IsPIDPtrEmpty(pid) {
		return nil, fmt.Errorf("pid is nil")
	}
	f := nactor.RootContext.RequestFuture(pid, send, timeout)
	iRecv, err := f.Result()
	if err != nil {
		return nil, err
	}
	recv, ok := iRecv.(*responseServicePayload)
	if !ok {
		return nil, fmt.Errorf("recv %#v is not responseServicePayload", recv)
	}
	return recv, nil
}

// 请求上传服务负载
type requestPutServicePayload struct {
	name    string
	id      nexport.ServiceID
	payload nexport.Payload
}

// 请求上传服务负载回复
type responsePutServicePayload struct {
	err error
}

func requestResponsePutServicePayload(pid *actor.PID, send *requestPutServicePayload) (*responsePutServicePayload, error) {
	return requestResponsePutServicePayloadT(pid, send, 10000*time.Millisecond)
}

func requestResponsePutServicePayloadT(pid *actor.PID, send *requestPutServicePayload, timeout time.Duration) (*responsePutServicePayload, error) {
	if nactor.IsPIDPtrEmpty(pid) {
		return nil, fmt.Errorf("pid is nil")
	}
	f := nactor.RootContext.RequestFuture(pid, send, timeout)
	iRecv, err := f.Result()
	if err != nil {
		return nil, err
	}
	recv, ok := iRecv.(*responsePutServicePayload)
	if !ok {
		return nil, fmt.Errorf("recv %#v is not responsePutServicePayload", recv)
	}
	return recv, nil
}

// 请求一组服务所有信息
type requestServiceGroupAllInfo struct {
	name string
}

// 请求一组服务所有信息回复
type responseServiceGroupAllInfo struct {
	err   error
	infos []*nservice.Info
}

func requestResponseServiceGroupAllInfo(pid *actor.PID, send *requestServiceGroupAllInfo) (*responseServiceGroupAllInfo, error) {
	return requestResponseServiceGroupAllInfoT(pid, send, 10000*time.Millisecond)
}

func requestResponseServiceGroupAllInfoT(pid *actor.PID, send *requestServiceGroupAllInfo, timeout time.Duration) (*responseServiceGroupAllInfo, error) {
	if nactor.IsPIDPtrEmpty(pid) {
		return nil, fmt.Errorf("pid is nil")
	}
	f := nactor.RootContext.RequestFuture(pid, send, timeout)
	iRecv, err := f.Result()
	if err != nil {
		return nil, err
	}
	recv, ok := iRecv.(*responseServiceGroupAllInfo)
	if !ok {
		return nil, fmt.Errorf("recv %#v is not responseServiceGroupAllInfo", recv)
	}
	return recv, nil
}

// 请求一组服务信息数量
type requestServiceInfoNum struct {
	name string
}

// 请求一组服务信息数量回复
type responseServiceInfoNum struct {
	err error
	num int
}

func requestResponseServiceInfoNum(pid *actor.PID, send *requestServiceInfoNum) (*responseServiceInfoNum, error) {
	return requestResponseServiceInfoNumT(pid, send, 10000*time.Millisecond)
}

func requestResponseServiceInfoNumT(pid *actor.PID, send *requestServiceInfoNum, timeout time.Duration) (*responseServiceInfoNum, error) {
	if nactor.IsPIDPtrEmpty(pid) {
		return nil, fmt.Errorf("pid is nil")
	}
	f := nactor.RootContext.RequestFuture(pid, send, timeout)
	iRecv, err := f.Result()
	if err != nil {
		return nil, err
	}
	recv, ok := iRecv.(*responseServiceInfoNum)
	if !ok {
		return nil, fmt.Errorf("recv %#v is not responseServiceInfoNum", recv)
	}
	return recv, nil
}

// 请求一组服务实例数量
type requestServiceInstanceNum struct {
	name string
}

// 请求一组服务信息数量回复
type responseServiceInstanceNum struct {
	err error
	num int
}

func requestResponseServiceInstanceNum(pid *actor.PID, send *requestServiceInstanceNum) (*responseServiceInstanceNum, error) {
	return requestResponseServiceInstanceNumT(pid, send, 10000*time.Millisecond)
}

func requestResponseServiceInstanceNumT(pid *actor.PID, send *requestServiceInstanceNum, timeout time.Duration) (*responseServiceInstanceNum, error) {
	if nactor.IsPIDPtrEmpty(pid) {
		return nil, fmt.Errorf("pid is nil")
	}
	f := nactor.RootContext.RequestFuture(pid, send, timeout)
	iRecv, err := f.Result()
	if err != nil {
		return nil, err
	}
	recv, ok := iRecv.(*responseServiceInstanceNum)
	if !ok {
		return nil, fmt.Errorf("recv %#v is not responseServiceInstanceNum", recv)
	}
	return recv, nil
}

// 请求循环选取服务实例
type requestRoundRobinPickService struct {
	name string
}

// 请求循环选取服务实例回复
type responseRoundRobinPickService struct {
	err  error
	info *nservice.Info
}

func requestResponseRoundRobinPickService(pid *actor.PID, send *requestRoundRobinPickService) (*responseRoundRobinPickService, error) {
	return requestResponseRoundRobinPickServiceInstanceT(pid, send, 10000*time.Millisecond)
}

func requestResponseRoundRobinPickServiceInstanceT(pid *actor.PID, send *requestRoundRobinPickService, timeout time.Duration) (*responseRoundRobinPickService, error) {
	if nactor.IsPIDPtrEmpty(pid) {
		return nil, fmt.Errorf("pid is nil")
	}
	f := nactor.RootContext.RequestFuture(pid, send, timeout)
	iRecv, err := f.Result()
	if err != nil {
		return nil, err
	}
	recv, ok := iRecv.(*responseRoundRobinPickService)
	if !ok {
		return nil, fmt.Errorf("recv %#v is not responseRoundRobinPickService", recv)
	}
	return recv, nil
}

type requestAddWatchCallback struct {
	cb WatchCallback
}

type responseAddWatchCallback struct {
	err error
}

func requestResponseAddWatchCallback(pid *actor.PID, send *requestAddWatchCallback) (*responseAddWatchCallback, error) {
	return requestResponseAddWatchCallbackT(pid, send, 5*time.Second)
}

func requestResponseAddWatchCallbackT(pid *actor.PID, send *requestAddWatchCallback, timeout time.Duration) (*responseAddWatchCallback, error) {
	if nactor.IsPIDPtrEmpty(pid) {
		return nil, fmt.Errorf("pid is nil")
	}
	f := nactor.RootContext.RequestFuture(pid, send, timeout)
	iRecv, err := f.Result()
	if err != nil {
		return nil, err
	}
	recv, ok := iRecv.(*responseAddWatchCallback)
	if !ok {
		return nil, fmt.Errorf("recv %#v is not responseAddWatchCallback", recv)
	}
	return recv, nil
}
